#include <iostream>
#include <list>
#include <vector>
#include <string>
#include "CuckooHash.h"

namespace ns3
{
// Edit by PassLink.cn
// 构造函数，初始化链表为空
CuckooHash::CuckooHash(int initialSize)
{
    table_size = initialSize;
    table1.resize(table_size);
    table2.resize(table_size);
}

int CuckooHash::hash_function1(const std::string &key)
{
    if (key.empty())
        return 0;
    int hash = key[0];
    hash = (hash << 5) + hash + key.back();
    return std::abs(hash) % table_size;
}

int CuckooHash::hash_function2(const std::string &key)
{
    if (key.empty())
        return 0;
    int hash = key[0] << 7;
    hash = (1000003 * hash) ^ key.back();
    return std::abs(hash) % table_size;
}

// 插入操作
// 数据插入桶   hashTable.insert_into("key1", 1);  hashTable.insert_into("key1", 1);
bool CuckooHash::insert_into(const std::string &key, const std::int32_t &value)
{
    int h1 = hash_function1(key);
    int h2 = hash_function2(key);
    // 两个桶都为空
    if (table1[h1].first.empty() && table2[h2].first.empty())
    {
        // 插入容量大的
        if (table1_capacity <= table2_capacity)
        {
            table2[h2] = std::make_pair(key, value);
            table2_capacity--;

            return true;
        }
        else
        {
            table1[h1] = std::make_pair(key, value);
            table1_capacity--;

            return true;
        }
    }
    // 两个桶不一定都为空
    // 桶h1为空时，插入
    if (table1[h1].first.empty())
    {
        // 如果存在key值
        if (table2[h2].first == key)
        {
            table2[h2].second++;
            return true;
        }
        table1[h1] = std::make_pair(key, value);
        table1_capacity--;
        return true;
    }
    // 桶h2为空时，插入
    if (table2[h2].first.empty())
    {
        // 如果存在key值
        if (table1[h1].first == key)
        {
            table1[h1].second++;
            return true;
        }
        table2[h2] = std::make_pair(key, value);
        table2_capacity--;
        return true;
    }
    // 两个桶都不为空
    // 如果存在key值
    if (table1[h1].first == key)
    {
        table1[h1].second++;
        return true;
    }
    // 如果存在key值
    if (table2[h2].first == key)
    {
        table2[h2].second++;
        return true;
    }

    // 两个桶的键都不匹配,踢出count小的值，重新找位置插入
    if (table2[h2].second <= table1[h1].second)
    {
        // 踢出限制
        if (KickCount > KickLimts)
        {
            nodeList.insert(key, value);
            KickCount = 0;
            return false;
        }
        // 记录踢出次数
        KickCount++;
        string key_temp = table2[h2].first;
        int value = table2[h2].second;
        // 占领
        table2[h2] = std::make_pair(key, value);
        // 重新找位置
        return insert_into(key_temp, value);
    }
    else
    {
        // 踢出限制
        if (KickCount > KickLimts)
        {
            nodeList.insert(key, value);
            KickCount = 0;
            return false;
        }
        // 记录踢出次数
        KickCount++;
        string key_temp = table1[h1].first;
        int value = table1[h1].second;
        // 占领
        table1[h1] = std::make_pair(key, value);
        // 重新找位置
        return insert_into(key_temp, value);
    }
    // 插入失败
    return false;
}

// 查询键值是否存在
// 查询键值是否存在，并返回对应的值
int32_t CuckooHash::search(const std::string &key)
{
    int h1 = hash_function1(key);
    int h2 = hash_function2(key);

    // 检查第一个哈希表
    if (table1[h1].first == key)
    {
        return float(table1[h1].second);
    }

    // 检查第二个哈希表
    if (table2[h2].first == key)
    {
        return float(table2[h2].second);
    }

    // 键值不存在
    return 0.0; // 或者根据具体需求返回一个指示不存在的特殊值
}

// 清空哈希表内存
void CuckooHash::clearMemory()
{
    table1.clear();
    table2.clear();
    nodeList.clear();
    // Kick 阈值
    KickCount = 0;
    // 哈希表容量
    table1_capacity = table_size;
    table2_capacity = table_size;

    table1.resize(table_size);
    table2.resize(table_size);
}

// 删除键值对
void CuckooHash::remove(const std::string &key)
{
    int h1 = hash_function1(key);
    int h2 = hash_function2(key);
    if (table1[h1].first == key)
    {
        table1[h1] = std::make_pair("", 0); // 清空对应位置的键值对
    }
    else if (table2[h2].first == key)
    {
        table2[h2] = std::make_pair("", 0); // 清空对应位置的键值对
    }
}

// 判断是否为大流
bool CuckooHash::isFloodStreamflow(const std::string &key)
{

    // 计算哈希表中所有计数的总和
    float allCount = 0.0;
    for (const auto &key_value : table1)
    {
        allCount += key_value.second;
    }
    for (const auto &key_value : table2)
    {
        allCount += key_value.second;
    }

    if (allCount <= 0)
    {
        return false;
    }

    // 查找key对应的count
    float m_res = search(key);
    if (!m_res)
    {
        // std::cout << "Not found key:" << key << std::endl;
        return false;
    }
    // 计算 Gk
    float G_k = m_res / allCount;

    // 计算阈值的分子和分母
    float G_th_molecular = 0.0;
    float G_th_denominator = 0.0;

    // 遍历哈希表计算阈值的分子和分母
    for (const auto &key_value : table1)
    {
        G_th_molecular += (key_value.second / allCount) * key_value.second;
        G_th_denominator += key_value.second;
    }
    // 遍历哈希表计算阈值的分子和分母
    for (const auto &key_value : table2)
    {
        G_th_molecular += (key_value.second / allCount) * key_value.second;
        G_th_denominator += key_value.second;
    }

    if (G_th_denominator <= 0)
    {
        return false;
    }
    // 计算阈值
    float G_th = G_th_molecular / G_th_denominator;

    // std::cout << "All count: " << allCount << std::endl;
    // std::cout << "G_k: " << G_k << std::endl;
    // std::cout << "G_th: " << G_th << std::endl;
    // 比较 Gk 和阈值
    // if (G_k > G_th)
    // {
    //     std::cout << key << " is Flood" <<  std::endl;
    // }else{
    //     std::cout << key <<" is not Flood" <<  std::endl;
    // }
    return (G_k > G_th);
}

// 打印table1的内容
void CuckooHash::printTable()
{
    std::cout << "Table1 content:" << std::endl;
    for (const auto &entry : table1)
    {
        std::cout << "Key: " << entry.first << ", Value: " << entry.second << std::endl;
    }
    std::cout << "Table2 content:" << std::endl;
    for (const auto &entry : table2)
    {
        std::cout << "Key: " << entry.first << ", Value: " << entry.second << std::endl;
    }
    std::cout << "nodeList content:" << std::endl;
    nodeList.print();
}
} //namespace
// int main()
// {

//     CuckooHash hashTable(3);
//     // 插入测试
//     hashTable.insert_into("1", 1);
//     hashTable.insert_into("2", 1);
//     hashTable.insert_into("3", 1);
//     hashTable.insert_into("4", 1);
//     hashTable.insert_into("5", 1);
//     hashTable.insert_into("6", 1);
//      // 打印
//     hashTable.printTable();
//      // 判断 key = "1" 是否属于大流
//     hashTable.isFloodStreamflow("1");
//     // 清理内存
//     hashTable.clearMemory();
//     // 打印
//     hashTable.printTable();
//     // 再次插入
//     hashTable.insert_into("2", 1);
//     hashTable.insert_into("3", 1);
//     hashTable.insert_into("4", 1);
//     hashTable.insert_into("5", 1);
//     hashTable.insert_into("6", 1);
//     hashTable.insert_into("6", 1);
//     hashTable.insert_into("6", 1);
//     hashTable.insert_into("6", 1);
//     // 打印
//     hashTable.printTable();
//     // 大流判断
//     hashTable.isFloodStreamflow("1");
//     hashTable.isFloodStreamflow("6");
//     hashTable.isFloodStreamflow("2");
//     return 0;
// }
